package org.dtrd.modules.archive.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.dtrd.common.exception.JeecgBootException;
import org.dtrd.common.util.DateUtils;
import org.dtrd.config.system.Constant;
import org.dtrd.config.system.Constant.PeriodUnit;
import org.dtrd.config.system.SystemState.ResponseState;
import org.dtrd.modules.achievement.entity.bean.PatientSigninPlan;
import org.dtrd.modules.achievement.entity.bean.SignInAction;
import org.dtrd.modules.achievement.entity.po.DtrdEntRdSigninPlan;
import org.dtrd.modules.achievement.service.IDtrdEntRdSigninPlanService;
import org.dtrd.modules.achievement.service.IDtrdEntRdSigninTemplateService;
import org.dtrd.modules.archive.entity.bean.ReverseSchemeDetail;
import org.dtrd.modules.archive.entity.bean.UpdateSigninTemplate;
import org.dtrd.modules.archive.entity.po.DtrdEntRdArchiveReverseScheme;
import org.dtrd.modules.archive.mapper.DtrdEntRdArchiveReverseSchemeMapper;
import org.dtrd.modules.archive.service.IDtrdEntRdArchiveReverseSchemeService;
import org.dtrd.modules.control.service.IDtrdEntRdSigninTargetDetailService;
import org.dtrd.modules.control.service.IDtrdEntRdSigninTargetService;
import org.dtrd.modules.patient.entity.bean.report.PatientServiceProgramme;
import org.dtrd.modules.patient.entity.bean.report.ReportTargetBean;
import org.dtrd.modules.service.entity.po.DtrdEntRdServicePackage;
import org.dtrd.modules.service.entity.po.DtrdRlPackagePatient;
import org.dtrd.modules.service.service.IDtrdEntRdServicePackageService;
import org.dtrd.modules.service.service.IDtrdRlPackagePatientService;
import org.dtrd.modules.util.ShiroUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


/**
 * <p>
 * 逆转方案 服务实现类
 * </p>
 *
 * @author QR
 * @since 2022-01-10
 */
@DS("multi-datasource1")
@Service
@Slf4j
public class DtrdEntRdArchiveReverseSchemeServiceImpl extends ServiceImpl<DtrdEntRdArchiveReverseSchemeMapper, DtrdEntRdArchiveReverseScheme> implements IDtrdEntRdArchiveReverseSchemeService {

    @Autowired
    private IDtrdEntRdSigninPlanService signinPlanService;
    @Autowired
    private IDtrdEntRdServicePackageService packageService;
    @Autowired
    private IDtrdRlPackagePatientService packagePatientRlService;
    @Autowired
    private IDtrdEntRdSigninTargetService targetService;
    @Autowired
    private IDtrdEntRdSigninTargetDetailService targetDetailService;
    @Autowired
    private IDtrdEntRdSigninTemplateService signinTemplateService;


    @Override
    public ReverseSchemeDetail getReverseScheme(Integer patientId) {
        DtrdEntRdArchiveReverseScheme dtrdEntRdArchiveReverseScheme = getOne(baseQueryWrapper()
                .eq(DtrdEntRdArchiveReverseScheme::getPatientId, patientId));
        return Optional.ofNullable(dtrdEntRdArchiveReverseScheme)
                .map(po -> new ReverseSchemeDetail().parseFromPo(po))
                .orElse(null);
    }

    @Override
    public DtrdEntRdArchiveReverseScheme getByPatientId(Integer patientId) {
        LambdaQueryWrapper<DtrdEntRdArchiveReverseScheme> wrapper = Wrappers.lambdaQuery(DtrdEntRdArchiveReverseScheme.class)
                .eq(DtrdEntRdArchiveReverseScheme::getPatientId, patientId)
                .orderByDesc(DtrdEntRdArchiveReverseScheme::getCreateTime)
                .eq(DtrdEntRdArchiveReverseScheme::getIsDel, 0)
                .last("limit 1");
        return getOne(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String saveReverseScheme(ReverseSchemeDetail dto) {
        // 设置患者打卡计划和周期
        Integer signinTemplateId = dto.getSigninTemplateId();
        Integer patientId = dto.getPatientId();
        Integer packageId = dto.getServiceTemplateId();
        DtrdEntRdServicePackage servicePackage = packageService.getById(packageId);
        if (servicePackage == null) {
            return ResponseState.STATE_PARAMS_ERROR.getMsg();
        }
        Date serviceStartTime = dto.getServiceStartTime();
        Date endTime = addTime(serviceStartTime, servicePackage.getPackageServicePeriod(), servicePackage.getPeriodUnit());
        String result = packagePatientRlService.checkServicePackageValid(patientId, serviceStartTime, endTime);
        if (result != null) {
            return result;
        }
        // 保存患者服务记录
        Integer relationId = packagePatientRlService.savePatientPackageRelation(patientId, packageId,servicePackage.getPeriodUnit(), serviceStartTime, endTime);

        // 保存打卡计划内容 打卡计划时间：服务开始时间 ～ 服务开始时间 + 服务包周期
        signinPlanService.savePatientSignInPlanFromTemplate(patientId, signinTemplateId, serviceStartTime, endTime);
        if (dto.getDataId() == null) {
            DtrdRlPackagePatient patientPackage = packagePatientRlService.getServicingPatientPackage(patientId);
            if (patientPackage == null) {
                // 增加限制 仅当前没有服务中服务包时新增控制目标
                // 仅在新增服务记录时，生成控制目标
                targetService.saveControlTarget(patientId, packageId, servicePackage.getPackageName(), serviceStartTime);
            }
        }

        // 保存逆转方案内容
        DtrdEntRdArchiveReverseScheme reverseScheme = new DtrdEntRdArchiveReverseScheme().parseFromDTO(dto);
        String userId = ShiroUtil.getLoginUserId();
        reverseScheme.setRelationId(relationId);
        reverseScheme.setCreateBy(userId);
        reverseScheme.setUpdateBy(userId);
        boolean save = save(reverseScheme);
        return save ? null : ResponseState.STATE_PARAMS_ERROR.getMsg();
    }

    @Override
    public boolean removeReverseScheme(Integer patientId) {
        return remove(baseQueryWrapper().eq(DtrdEntRdArchiveReverseScheme::getPatientId, patientId));
    }

    @Override
    public PatientServiceProgramme getPatientServiceProgramme(Integer patientId) {
        PatientServiceProgramme serviceProgramme = packagePatientRlService.getPatientServiceProgramme(patientId);
        if (serviceProgramme == null) {
            return null;
        }
//        PatientServiceProgramme serviceProgramme = new PatientServiceProgramme();
//
//        DtrdEntRdArchiveReverseScheme scheme = getOne(Wrappers.lambdaQuery(DtrdEntRdArchiveReverseScheme.class)
//                .eq(DtrdEntRdArchiveReverseScheme::getIsDel, 0)
//                .eq(DtrdEntRdArchiveReverseScheme::getPatientId, patientId).last("limit 1"));
//        // 服务方案
//        if (scheme != null) {
//            Integer packageId = scheme.getServiceTemplateId();
//            if (packageId != null) {
//                serviceProgramme.setServiceName(packageService.getPackageName(packageId));
//                serviceProgramme.setServicePeriod(packagePatientRlService.getPackageServicePeriod(patientId, packageId));
//            }
//            // 饮食 运动 用药计划
//            serviceProgramme = serviceProgramme.parseFromPO(scheme);
//        }

        // 目标值
        String targetName = targetService.getFirstTargetName(patientId);
        if (StrUtil.isNotBlank(targetName)) {
            serviceProgramme.setTargetName(targetName);
        }
        List<ReportTargetBean> targets = targetDetailService.getReportFirstTargets(patientId);
        if (CollectionUtil.isNotEmpty(targets)) {
            serviceProgramme.setTargets(JSONUtil.parseArray(targets));
        }
        // 打卡计划
        PatientSigninPlan signinPlan = signinPlanService.getSigninPlan(patientId);
        serviceProgramme.setSigninPlan(signinPlan);
        return serviceProgramme;
    }

    @Override
    public String getTemplateByPatientId(Integer patientId) {
        DtrdEntRdArchiveReverseScheme scheme = getByPatientId(patientId);
        if (scheme == null) {
            throw new JeecgBootException("该患者没有逆转方案!");
        }
        Integer signinTemplateId = scheme.getSigninTemplateId();
        return Optional.ofNullable(signinTemplateId).map(id -> signinTemplateService.getTemplateNameById(id)).orElse(null);
    }

    @Override
    public DtrdEntRdArchiveReverseScheme getRecordByRelationId(Integer relationId) {
        LambdaQueryWrapper<DtrdEntRdArchiveReverseScheme> wrapper = baseQueryWrapper().eq(DtrdEntRdArchiveReverseScheme::getRelationId, relationId);
        return getOne(wrapper);
    }

    @Override
    public boolean updateReverseSchemeSigninTemplate(UpdateSigninTemplate signinTemplate)
    {

        DtrdEntRdArchiveReverseScheme reverseScheme = getOne(Wrappers.lambdaQuery(DtrdEntRdArchiveReverseScheme.class)
                .eq(DtrdEntRdArchiveReverseScheme::getIsDel, 0)
                .eq(DtrdEntRdArchiveReverseScheme::getPatientId, signinTemplate.getPatientId())
                .eq(DtrdEntRdArchiveReverseScheme::getSigninTemplateId, signinTemplate.getOldSigninTemplateId())
                .eq(DtrdEntRdArchiveReverseScheme::getServiceStartTime, DateUtils.formatDate(signinTemplate.getServiceStartTime()))
                .last("limit 1"));

        // DtrdEntRdArchiveReverseScheme reverseScheme = getById(signinTemplate.getDataId());
        log.info("reverseScheme=====" + reverseScheme);
        if (reverseScheme != null) {
            reverseScheme.setSigninTemplateId(signinTemplate.getSigninTemplateId());
            String userId = ShiroUtil.getLoginUserId();
            reverseScheme.setUpdateBy(userId);
            boolean updateReverseScheme = updateById(reverseScheme);
            log.info("updateReverseScheme=====>>" + updateReverseScheme);
            if (updateReverseScheme) {
                DtrdEntRdServicePackage servicePackage = packageService.getById(reverseScheme.getServiceTemplateId());
                log.info("servicePackage=====>>>>>>" + servicePackage);
                if (servicePackage != null) {
                    // 把所有plan改为已完成
                    Date endTime = addTime(reverseScheme.getServiceStartTime(), servicePackage.getPackageServicePeriod(), servicePackage.getPeriodUnit());
                    signinPlanService.finishPatientSignInPlan(reverseScheme.getPatientId(), reverseScheme.getServiceStartTime(), endTime, null);

                    // 添加新的打卡计划
                    signinPlanService.savePatientSignInPlanFromTemplate(
                            reverseScheme.getPatientId(),
                            signinTemplate.getSigninTemplateId(),
                            reverseScheme.getServiceStartTime(),
                            endTime);
                    return true;
                }
            }
        }
        return false;
    }

    @SuppressWarnings("all")
    private List<JSONObject> getSignPlan(String signJson) {
        List<SignInAction> signInActions = JSONObject.parseArray(signJson, SignInAction.class);
        List<JSONObject> signPlans = new ArrayList<>(24);
        for (SignInAction signInAction : signInActions) {
            if (StrUtil.isNotBlank(signInAction.getStarttime()) && StrUtil.isNotBlank(signInAction.getEndtime())) {
                Integer recordType = signInAction.getRecordType();
                Integer subType = signInAction.getSubType();
                JSONObject plan = new JSONObject();
                StringJoiner joiner = new StringJoiner("");
                if (subType != null) {
                    if (recordType == Constant.RecordType.SUGAR.getType()) {
                        joiner.add(Constant.SugarRecordType.valueOf(subType).getName());
                    }
                    if (recordType == Constant.RecordType.DIET.getType()) {
                        joiner.add(Constant.FoodRecordType.valueOf(subType).getName());
                    }
                    if (recordType == Constant.RecordType.MEDICAL.getType()) {
                        joiner.add(Constant.MedicalRecordType.valueOf(subType).getName());
                    }
                    if (recordType == Constant.RecordType.INSULIN.getType()) {
                        joiner.add(Constant.InsulinRecordType.valueOf(subType).getName());
                    }
                    if (recordType == Constant.RecordType.BLOOD_PRESSURE.getType()) {
                        joiner.add(Constant.BloodPressureRecordType.valueOf(subType).getName());
                    }
                }
                if (recordType != null) {
                    joiner.add(Constant.RecordType.valueOf(recordType).getName());
                }
                plan.put("signinName", joiner.toString());
                String starttime = signInAction.getStarttime();
                String endtime = signInAction.getEndtime();
                plan.put("time", starttime + " ~ " + endtime);
                signPlans.add(plan);
            }
        }
        return signPlans;
    }

    private LambdaQueryWrapper<DtrdEntRdArchiveReverseScheme> baseQueryWrapper() {
        return Wrappers.lambdaQuery(DtrdEntRdArchiveReverseScheme.class)
                .eq(DtrdEntRdArchiveReverseScheme::getIsDel, 0);
    }

    private LambdaUpdateWrapper<DtrdEntRdArchiveReverseScheme> baseUpdateWrapper() {
        return Wrappers.lambdaUpdate(DtrdEntRdArchiveReverseScheme.class)
                .eq(DtrdEntRdArchiveReverseScheme::getIsDel, 0);
    }

    private Date addTime(Date date, Integer month, Integer periodUnit) {
        DateTime dateTime = new DateTime(date);
        dateTime.offset(Optional.ofNullable(Constant.PeriodUnit.valueOf(periodUnit)).orElse(PeriodUnit.MONTH).getField(), month);
        return dateTime;
    }
}
